#ifndef B_H
#define B_H 

#include <iostream>
#include <string>
#include <vector>


#include <QWidget>

 class QLabel;
 class QLineEdit;
 class QTextEdit;
 class QPushButton;
 class QString;
 class Player;
 class Game;

 class Canvas : public QWidget
 {
        Q_OBJECT

 public:
        Canvas(QWidget *parent = 0);
        void setHostStateLabel(QString &s);
        void setPlayerStateLabel(QString &s);
        void setResultLabel(QString &s);

 public slots:
        void startBtn();
        void hitBtn();
        void standBtn();
        void shuffleBtn();

 private:
        QPushButton *startButton;
        QPushButton *hitButton;
        QPushButton *standButton;
        QPushButton *shuffleButton;
        QLabel *hostState;
        QLabel *playerState;
        QLabel *result;
        Game *myGame;
 };


using namespace std;


class Card
{
public:
    enum Rank {ACE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN,
               JACK, QUEEN, KING};           
    enum Suit {CLUBS, DIAMONDS, HEARTS, SPADES};

    //overloading << operator so can send Card object to standard output 
    friend ostream& operator<<(ostream& os, const Card& aCard);
    
    Card(Rank r = ACE, Suit s = CLUBS, bool ifu = true); 

    //returns the value of a card, 1 - 11
    int getValue() const;

    //flips a card; if face up, becomes face down and vice versa
    void flip();
    
private:
    Rank rank;
    Suit suit;
    bool isFaceUp;
    Canvas *canvas;
};

class Hand
{

public:
    Hand();
    
    virtual ~Hand();

    //adds a card to the hand
    void add(Card* pCard);
 
    //clears hand of all cards
    void clear();

    int getTotal() const;
protected:
    vector<Card*> cards;
};

class AbstractPlayer : public Hand 
{
    friend ostream& operator<<(ostream& os, const AbstractPlayer& aAbstractPlayer);
    void makeString(string& s);

public:
    AbstractPlayer(const string& s = "");
    
    virtual ~AbstractPlayer();

    //indicates whether or not generic player wants to keep hitting
    virtual bool isHitting() const = 0;

    //returns whether generic player has busted - has a total greater than 21
    bool isBusted() const;

    //announces that the generic player busts
    void bust() const;

    QString& getLabelQStr() const;
    string getName() const;

protected:
    string name;
    Hand *hand;
    mutable QString labelQStr;
};

class Player : public AbstractPlayer
{
public:
    Player(bool histPressed = false, const string& name = "");

    virtual ~Player();

    //returns whether or not the player wants another hit       
    virtual bool isHitting() const;

    //announces that the player wins
    void win() const;

    //announces that the player loses
    void lose() const;

    //announces that the player pushes
    void push() const;

    void setHitPressed();

private:
    bool hitPressed;
};

class House : public AbstractPlayer
{
public:
    House(const string& name = "House");

    virtual ~House();

    //indicates whether house is hitting - will always hit on 16 or less
    virtual bool isHitting() const;
  
    //flips over first card
    void flipFirstCard();
};

class Deck : public Hand
{
public:
    Deck();
    
    virtual ~Deck();

    //create a standard deck of 52 cards
    void populate();

    //shuffle cards
    void shuffle();

    //deal one card to a hand
    void deal(Hand& aHand);

    //give additional cards to an abstract player 
    void additionalCards(AbstractPlayer& aAbstractPlayer);

};

class Game
{
public:
    Game(const vector<string>& names, Canvas *cnv);
    
    ~Game();
    
    //plays the game of blackjack    
    void setupTable();
    void PlayB();
 //   void startGame();
    void hitSelected();


private:
    Deck deck;
    House house;
    vector<Player> player;  
    Canvas *canvas;
};
#endif
